package com.yfunc.common.persistence.defaults;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import com.yfunc.common.persistence.Query;
import com.yfunc.common.persistence.Session;
import com.yfunc.common.persistence.SessionFactory;
import com.yfunc.common.persistence.defaults.SqlSessionTemplate.Call;
import com.yfunc.common.persistence.ibatis.EntityMapper;
import com.yfunc.common.persistence.sql.SQLQuery;

public class DefaultSession extends AbstractTemplate implements Session {
	
	private SessionFactory sessionFactory;

	public DefaultSession(SqlSessionFactory sqlSessionFactory , SessionFactory sessionFactory) {
		super(sqlSessionFactory);
		this.sessionFactory = sessionFactory;
	}

	@Override
	public int insert(final Object entity) {
		return getTemplate().call(new Call<Integer>() {
			public Integer on(SqlSession session) {
				EntityMapper mapper = session.getMapper(EntityMapper.class);
				return mapper.insert(entity);
			}
		});
	}

	@Override
	public int update(final Object entity) {
		return getTemplate().call(new Call<Integer>() {
			public Integer on(SqlSession session) {
				EntityMapper mapper = session.getMapper(EntityMapper.class);
				return mapper.update(entity);
			}
		});
	}

	@Override
	public int delete(final Object entity) {
		return getTemplate().call(new Call<Integer>() {
			public Integer on(SqlSession session) {
				EntityMapper mapper = session.getMapper(EntityMapper.class);
				return mapper.delete(entity);
			}
		});
	}

	@Override
	public int delete(final Class<?> entityClass, final Object pk) {

		return getTemplate().call(new Call<Integer>() {
			public Integer on(SqlSession session) {
				EntityMapper mapper = session.getMapper(EntityMapper.class);
				return mapper.deleteById(entityClass, pk);
			}
		});
	}

	@Override
	public <T> T load(final Class<T> entityClass, final Object pk) {

		return getTemplate().call(new Call<T>() {
			public T on(SqlSession session) {
				EntityMapper mapper = session.getMapper(EntityMapper.class);
				return (T) mapper.findById(entityClass, pk);
			}
		});
	}

	@Override
	public <T> List<T> loadAll(final Class<T> entityClass) {
		return getTemplate().call(new Call<List<T>>() {
			public List<T> on(SqlSession session) {
				EntityMapper mapper = session.getMapper(EntityMapper.class);
				return (List<T>) mapper.findAll(entityClass);
			}
		});
	}
	
	

	@Override
	public <T> T selectOne(final String statement) {
		return getTemplate().call(new Call<T>() {
			@Override
			public T on(SqlSession session) {
				return session.selectOne(statement);
			}
		});
	}

	@Override
	public <T> T selectOne(final String statement, final Object parameter) {
		return getTemplate().call(new Call<T>() {
			@Override
			public T on(SqlSession session) {
				return session.selectOne(statement, parameter);
			}
		});
	}

	@Override
	public <E> List<E> selectList(final String statement) {
		return getTemplate().call(new Call<List<E>>() {
			@Override
			public List<E> on(SqlSession session) {
				return session.selectList(statement);
			}
		});
	}

	@Override
	public <E> List<E> selectList(final String statement, final Object parameter) {
		return getTemplate().call(new Call<List<E>>() {
			@Override
			public List<E> on(SqlSession session) {
				return session.selectList(statement, parameter);
			}
		});
	}
	
	@Override
	public <T> Query createQuery(Class<T> entityClass) {
		return new DefaultQuery<T>(entityClass , new SQLQuery(sessionFactory.getDataSource()));
	}

	@Override
	public <T> List<T> query(Class<T> entityClass, String ql, Object... anArguments) {
		SQLQuery query = new SQLQuery(sessionFactory.getDataSource());
		return query.queryObjects(entityClass, ql, anArguments);
	}

	

}
